package org.origin.centre.utils;

import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import java.util.HashMap;
import java.util.Map;

/**
 * 响应工具类
 *
 * @author ferret
 * @version 2024-05-08
 */
@SuppressWarnings("unused")
public final class ResponseUtil {
    /**
     * JSON消息转换器
     */
    protected static final HttpMessageConverter<Object> messageConverterJson = new MappingJackson2HttpMessageConverter();

    /**
     * 成功响应，仅包含消息
     *
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @param message  响应消息
     */
    public static void success(HttpServletResponse response, String message) {
        response(response, HttpStatus.OK, HttpStatus.OK, message, null);
    }

    /**
     * 成功响应，包含消息和数据
     *
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @param message  响应消息
     * @param data     响应数据
     */
    public static void success(HttpServletResponse response, String message, Object data) {
        response(response, HttpStatus.OK, HttpStatus.OK, message, data);
    }

    /**
     * 失败响应，仅包含消息
     *
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @param message  响应消息
     */
    public static void failure(HttpServletResponse response, String message) {
        response(response, HttpStatus.OK, HttpStatus.BAD_REQUEST, message, null);
    }

    /**
     * 失败响应，包含消息和数据
     *
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @param message  响应消息
     * @param data     响应数据
     */
    public static void failure(HttpServletResponse response, String message, Object data) {
        response(response, HttpStatus.OK, HttpStatus.BAD_REQUEST, message, data);
    }

    /**
     * 自定义失败响应，包含自定义状态码和消息
     *
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @param status   自定义状态码
     * @param message  响应消息
     */
    public static void failure(HttpServletResponse response, HttpStatus status, String message) {
        response(response, HttpStatus.OK, status, message, null);
    }

    /**
     * 构建并发送带有状态、消息和数据的HTTP响应
     *
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @param httpStatus HTTP状态码
     * @param status     自定义状态码
     * @param message    响应消息
     * @param data       响应数据
     */
    public static void response(HttpServletResponse response, HttpStatus httpStatus, HttpStatus status, String message, Object data) {
        try {
            // 创建结果映射，包含状态、消息和数据
            Map<String, Object> result = new HashMap<>();
            result.put("status", status.value());
            result.put("message", message);
            if (null != data) {
                result.put("data", data);
            }
            response(response, httpStatus, result);
        } catch (Exception e) {
            // 捕获异常并抛出IllegalArgumentException
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * 构建并发送带有状态、消息和数据的HTTP响应
     *
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @param status   HttpStatus对象，表示HTTP状态码
     * @param data     响应数据，可选参数，可以为空
     */
    public static void response(HttpServletResponse response, HttpStatus status, Object data) {
        try {
            // 使用ServletServerHttpResponse封装HTTP响应，并设置状态码
            ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
            httpResponse.setStatusCode(status);
            // 数据不为空时，直接将数据写入HTTP响应
            messageConverterJson.write(data, null, httpResponse);
        } catch (Exception e) {
            // 捕获异常并抛出IllegalArgumentException
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * 构建并返回一个ModelAndView对象，用于视图响应
     *
     * @param resultType 结果类型，用于决定HTTP状态码
     * @param status     HttpStatus对象，表示HTTP状态码
     * @param message    响应信息，向客户端传达具体信息
     * @return ModelAndView对象，包含状态码和响应信息
     */
    public static ModelAndView responseView(Integer resultType, HttpStatus status, String message) {
        ModelAndView mv = new ModelAndView();
        // 设置HTTP状态码，根据resultType决定是否使用传入的状态码
        mv.setStatus(resultType != null && resultType == 2 ? status : HttpStatus.OK);
        // 添加状态码到模型
        mv.addObject("status", status.value());
        // 添加消息到模型，并将换行符替换为HTML换行标签
        mv.addObject("message", message.replaceAll("\n", "<br/>"));
        return mv;
    }

    /**
     * 构建并返回一个ModelAndView对象，用于JSON响应
     *
     * @param resultType 结果类型，用于决定HTTP状态码
     * @param status     HttpStatus对象，表示HTTP状态码
     * @param message    响应信息，向客户端传达具体信息
     * @return ModelAndView对象，包含状态码和响应信息
     */
    public static ModelAndView responseJson(Integer resultType, HttpStatus status, String message) {
        ModelAndView mv = new ModelAndView();
        // 设置视图，使用MappingJackson2JsonView将模型转换为JSON
        mv.setView(new MappingJackson2JsonView());
        // 设置HTTP状态码，根据resultType决定是否使用传入的状态码
        mv.setStatus(resultType != null && resultType == 2 ? status : HttpStatus.OK);
        // 添加状态码到模型
        mv.addObject("status", status.value());
        // 添加消息到模型
        mv.addObject("message", message);
        return mv;
    }
}
